package com.azxc.rapid.plus.user.service.impl;


import com.azxc.rapid.common.constant.CommonConstant;
import com.azxc.rapid.common.constant.TenantConstant;
import com.azxc.rapid.core.log.exception.ServiceException;
import com.azxc.rapid.core.mp.base.BaseServiceImpl;
import com.azxc.rapid.core.mp.support.Condition;
import com.azxc.rapid.core.secure.utils.AuthUtil;
import com.azxc.rapid.core.tenant.RapidTenantProperties;
import com.azxc.rapid.core.tool.api.R;
import com.azxc.rapid.core.tool.constant.RapidConstant;
import com.azxc.rapid.core.tool.jackson.JsonUtil;
import com.azxc.rapid.core.tool.node.ForestNodeMerger;
import com.azxc.rapid.core.tool.support.Kv;
import com.azxc.rapid.core.tool.utils.*;
import com.azxc.rapid.plus.user.mapper.UserPlusMapper;
import com.azxc.rapid.plus.user.service.IUserDeptPlusService;
import com.azxc.rapid.plus.user.service.IUserOauthPlusService;
import com.azxc.rapid.plus.user.service.IUserPlusService;
import com.azxc.rapid.plus.user.vo.DeptUserVO;
import com.azxc.rapid.plus.user.vo.UserTreeVO;
import com.azxc.rapid.system.cache.ParamCache;
import com.azxc.rapid.system.cache.SysCache;
import com.azxc.rapid.system.entity.Tenant;
import com.azxc.rapid.system.feign.ISysClient;
import com.azxc.rapid.system.user.entity.*;
import com.azxc.rapid.system.user.enums.UserEnum;
import com.azxc.rapid.system.user.vo.UserVO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.regex.Pattern;

import static com.azxc.rapid.common.constant.CommonConstant.DEFAULT_PARAM_PASSWORD;

/**
 * 服务实现类
 */
@Service
public class UserPlusServiceImpl extends BaseServiceImpl<UserPlusMapper, User> implements IUserPlusService {
	private static final String GUEST_NAME = "guest";

	@Autowired
	private IUserDeptPlusService userDeptService;

	@Autowired
	private IUserOauthPlusService userOauthService;

	@Autowired
	private ISysClient sysClient;
	@Autowired
	private RapidTenantProperties tenantProperties;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean submit(User user) {
		if (StringUtil.isBlank(user.getTenantId())) {
			user.setTenantId(RapidConstant.ADMIN_TENANT_ID);
		}
		String tenantId = user.getTenantId();
		Tenant tenant = SysCache.getTenant(tenantId);
		if (Func.isNotEmpty(tenant)) {
			Integer accountNumber = tenant.getAccountNumber();
			if (tenantProperties.getLicense()) {
				String licenseKey = tenant.getLicenseKey();
				String decrypt = DesUtil.decryptFormHex(licenseKey, TenantConstant.DES_KEY);
				accountNumber = JsonUtil.parse(decrypt, Tenant.class).getAccountNumber();
			}
			Integer tenantCount = baseMapper.selectCount(Wrappers.<User>query().lambda().eq(User::getTenantId, tenantId));
			if (accountNumber != null && accountNumber > 0 && accountNumber <= tenantCount) {
				throw new ServiceException("当前租户已到最大账号额度!");
			}
		}
		if (Func.isNotEmpty(user.getPassword())) {
			user.setPassword(DigestUtil.encrypt(user.getPassword()));
		}
		Integer userCount = baseMapper.selectCount(Wrappers.<User>query().lambda().eq(User::getTenantId, tenantId).eq(User::getAccount, user.getAccount()));
		if (userCount > 0 && Func.isEmpty(user.getId())) {
			throw new ServiceException(StringUtil.format("当前用户 [{}] 已存在!", user.getAccount()));
		}
		return save(user) && submitUserDept(user);
	}


	@Override
	public boolean updateUserInfo(User user) {
		user.setPassword(null);
		return updateById(user);
	}

	private boolean submitUserDept(User user) {
		List<Long> deptIdList = Func.toLongList(user.getDeptId());
		List<UserDept> userDeptList = new ArrayList<>();
		deptIdList.forEach(deptId -> {
			UserDept userDept = new UserDept();
			userDept.setUserId(user.getId());
			userDept.setDeptId(deptId);
			userDeptList.add(userDept);
		});
		userDeptService.remove(Wrappers.<UserDept>update().lambda().eq(UserDept::getUserId, user.getId()));
		return userDeptService.saveBatch(userDeptList);
	}



	@Override
	public UserInfo userInfo(Long userId) {
		User user = baseMapper.selectById(userId);
		return buildUserInfo(user);
	}



	private UserInfo buildUserInfo(User user) {
		return buildUserInfo(user, UserEnum.WEB);
	}

	private UserInfo buildUserInfo(User user, UserEnum userEnum) {
		UserInfo userInfo = new UserInfo();
		userInfo.setUser(user);
		if (Func.isNotEmpty(user)) {
			R<List<String>> result = sysClient.getRoleAliases(user.getRoleId());
			if (result.isSuccess()) {
				List<String> roleAlias = result.getData();
				userInfo.setRoles(roleAlias);
			}
		}
		// 根据每个用户平台，建立对应的detail表，通过查询将结果集写入到detail字段
		Kv detail = Kv.create().set("type", userEnum.getName());
		if (userEnum == UserEnum.WEB) {
			UserWeb userWeb = new UserWeb();
			UserWeb query = userWeb.selectOne(Wrappers.<UserWeb>lambdaQuery().eq(UserWeb::getUserId, user.getId()));
			if (ObjectUtil.isNotEmpty(query)) {
				detail.set("ext", query.getUserExt());
			}
		} else if (userEnum == UserEnum.APP) {
			UserApp userApp = new UserApp();
			UserApp query = userApp.selectOne(Wrappers.<UserApp>lambdaQuery().eq(UserApp::getUserId, user.getId()));
			if (ObjectUtil.isNotEmpty(query)) {
				detail.set("ext", query.getUserExt());
			}
		} else {
			UserOther userOther = new UserOther();
			UserOther query = userOther.selectOne(Wrappers.<UserOther>lambdaQuery().eq(UserOther::getUserId, user.getId()));
			if (ObjectUtil.isNotEmpty(query)) {
				detail.set("ext", query.getUserExt());
			}
		}
		userInfo.setDetail(detail);
		return userInfo;
	}





	@Override
	public UserVO getUserVoInfo() {
		Long userId = AuthUtil.getUserId();
		return baseMapper.getUserVoInfo(userId + "");
	}

	@Override
	public List<UserTreeVO> loadAllTree() {
		List<UserTreeVO> tree = ForestNodeMerger.merge(baseMapper.deptAllTree());
		for (UserTreeVO userTreeVO : tree) {
			if (Func.isNotEmpty(userTreeVO.getChildren())) {
				userTreeVO.setDisabled(true);
			}
		}
		return tree;
	}

	@Override
	public Collection<? extends UserTreeVO> loadTree(long deptId) {
		return ForestNodeMerger.merge(baseMapper.deptTree(deptId));
	}

	@Override
	public List<User> selectUserByDept(DeptUserVO deptUserVO) {
		List<User> users = new ArrayList<>();
		if (Func.isEmpty(deptUserVO.getSearch()) && Func.isNotEmpty(deptUserVO.getDeptIds())) {
			List<String> deptIds = deptUserVO.getDeptIds();
			for (String deptId : deptIds) {
				List<User> userList = baseMapper.selectUserByDept(deptId);
				users.addAll(userList);
			}
		}
		if (Func.isEmpty(deptUserVO.getDeptIds()) && Func.isNotEmpty(deptUserVO.getSearch())){
			Pattern patternNum = Pattern.compile("[0-9]*");
			Pattern patternChar = Pattern.compile("^[\\u4e00-\\u9fa5]{0,}$");
			if (patternNum.matcher(deptUserVO.getSearch()).matches()){
				users.addAll(baseMapper.selectUserByPhone(deptUserVO.getSearch()));
			}else if (patternChar.matcher(deptUserVO.getSearch()).matches()){
				users.addAll( baseMapper.selectUserByName(deptUserVO.getSearch()));
			}
		}
		return users;
	}


	@Override
	public List<UserTreeVO> allTree() {
		return ForestNodeMerger.merge(baseMapper.allTree());
	}

	@Override
	public List<UserTreeVO> tree(long deptId) {
		return ForestNodeMerger.merge(baseMapper.tree(deptId));
	}


	@Override
	public List<User> selectUserByRegionCode(String regionCode) {
		return baseMapper.selectUserByRegionCode(regionCode);
	}

	@Override
	public List<Long> getStorageIdList() {
		return baseMapper.getStorageByUserId(AuthUtil.getUserId());
	}


	@Override
	public IPage<User> userByRoleTraceInstitute(IPage<User> page) {
		return baseMapper.userByRoleAlias(page, "trace_institute");
	}

	@Override
	public void updateUserEntId(User user) {
		baseMapper.updateUserEntId(user);
	}
}
